home *** CD-ROM | disk | FTP | other *** search
- /*
- $title ('yam4.c: CIS A protocol')
- $date (20 mar 85)
- */
- /*
- *
- * Support for Compuserve CIS A protocol
- * file-upload and file-download functions
- * called from term() when ascii SI is received.
- *
- * It seems that the CIS protocol isn't quite as simple as YAM4.C
- * was lead to beleive! 1) The SI and SO may have the high-order
- * bit on, as SI and SO without the high order bit on are used to
- * control external network echoing. 2) If you R FILTRN, then a
- * "redundant" SI is issued when FILTRN transfers control to
- * XFTRAN without sending an SO. 3) Sometimes CIS ends a transfer
- * without any SO at all, just starts sending (with a blank).
- * 5) The fixes therein allow downloading from Micro-quote
- * via TymNet. DAVID WELCH
- */
-
- #include "yam.h"
-
- FLAG CISasc; /* CIS xfer is in ascii mode */
- char ciscursec; /* Sector number just received by cisgetsec() */
-
- cispa()
- {
- register char *p;
-
- for(;;) {
- switch( firstch=readbyte(400)) {
- case ESC:
- switch(firstch=readbyte(400)) {
- case 'I':
- pstat("CIS-IDENT");
- p = MYSYSTEM;
- while( *p)
- sendbyte( *p++);
- continue;
- case 'A':
- if(cisxfer() != ERROR)
- continue;
- sendline(NAK); return ERROR;
- default:
- break;
- }
- default:
- lprintf("Bad CIS request 0%o\n", firstch);
- return ERROR;
- case '\n':
- case SO:
- case (SO | 0x80):
- case ' ':
- return OK;
- case SI:
- case (SI | 0x80):
- break;
- }
- }
- }
-
- /*
- * get file request from host and perform the transfer
- */
- cisxfer()
- {
- char *p;
- CISasc = FALSE;
- if(cisgetsec(Utility.ubuf, (PATHLEN+3)) <= 0)
- return ERROR;
- if(p=index('\r', Utility.ubuf))
- *p = 0;
- CISasc = (Utility.ubuf[1] == 'A');
-
- if(Utility.ubuf[0] == 'U') {
- if(opentx( &Utility.ubuf[2]) == ERROR)
- return ERROR;
- sendbyte('.');
- if(readbyte(400) != '.' || sendcis() == ERROR) {
- closetx(FALSE); return ERROR;
- }
- closetx(TRUE); return OK;
- }
- else if(Utility.ubuf[0] == 'D') {
- if(openrx( &Utility.ubuf[2]) == ERROR) {
- return ERROR;
- }
- sendbyte('.');
- return getcis();
- }
- else
- return ERROR;
- }
-
- sendcis()
- {
- unsigned nchars;
-
- nchars=0;
- while((wcj=filbcis(Utility.ubuf)) > 0) {
- pstat("Char %u", nchars);
- if(scisrec(Utility.ubuf, wcj)==ERROR)
- return ERROR;
- nchars += wcj;
- }
- return scisrec(0,0); /* send special EOT record */
- }
-
- /*
- * fill p with at most 256 chars not incl EOF
- * returns number of chars fetched, 0 for end of file
- */
- filbcis(p)
- char *p;
- {
- int c;
- int count;
- for( count=0; count< 256; ++count) {
- if((c=getc(fin)) == EOF)
- break;
- if(CISasc && c == CPMEOF) {
- ungetc(CPMEOF, fin); break;
- }
- *p++ =c;
- }
- return count;
- }
- /*
- * send a record at buf with length len to CIS
- * return ERROR if unsuccessful
- * Special case: len==0 causes EOT record to be sent
- * instead of buffer contents
- */
- scisrec( buf, len)
- char *buf;
- {
- char *p;
- int count;
- int retry;
- if( ++ciscursec > '9')
- ciscursec = '0';
- for(retry = 5; --retry; ++toterrs) {
- p = buf; sendbyte(SOH);
- sendbyte(oldcrc=ciscursec);
- if(len==0) {
- sendbyte(firstch=EOT);
- ucksum();
- } else
- for(count=len; --count >=0;) {
- firstch = *p++ & 0377;
- ucksum();
- sendmsk(firstch);
- if(CISasc)
- putcty(firstch);
- }
- sendbyte(ETX);
- sendmsk(oldcrc);
- if((firstch=readbyte(400)) == '.')
- return OK;
- if (CISasc)
- lprintf("\n");
- lprintf("Got 0%o for record ACK\n", firstch);
- if(firstch < 0)
- return ERROR;
- }
- return ERROR;
- }
-
- /*
- * send most control charsacters as DLE sequence
- * except for BEL to CR inclusive
- */
- sendmsk(c)
- unsigned c;
- {
- c &= 0377; /* in case of sign extension */
- if( c < 7 || (c < 0x20 && c > 0x0D)) {
- sendbyte(DLE);
- sendbyte(c | 0x40);
- }
- else
- sendbyte(c);
- }
-
- /*
- * get (download) a file with CIS A protocol
- */
- getcis()
- {
- char cursec;
- char *p;
- unsigned nchars;
-
- cursec = '1'; nchars=0;
- for(;;) {
- pstat("Char %u", nchars);
- doagain:
- if((wcj=cisgetsec(Utility.ubuf, KSIZE)) <= 0)
- break;
- if(ciscursec==EOT)
- break;
- if(ciscursec == cursec) {
- sendbyte('.');
- goto doagain;
- }
- if(ciscursec == cursec+1 ||
- (cursec == '9' && ciscursec == '0') ) {
- nchars += wcj;
- for(p=Utility.ubuf; --wcj >= 0; )
- fputc( *p++, fout);
- if( ++cursec > '9')
- cursec = '0';
- sendbyte('.');
- }
- else {
- if (CISasc)
- lprintf("\n");
- lprintf("Got record 0%o expecting 0%o\n",
- ciscursec, cursec);
- break;
- }
- }
- lprintf("%u Characters Received ", nchars);
- if(ciscursec != EOT) {
- closerx(TRUE); return ERROR;
- }
- if(CISasc)
- fputc(CPMEOF, fout);
- closerx(FALSE); sendbyte('.'); return OK;
- }
- /*
- * gets a CIS A protocol record into buf. Record number returned in global
- * ciscursec, which equals EOT for EOT record (end of file). Returns number
- * of characters read. Returns ERROR if too many chars received.
- * no retry count; it is assumed that sender will send NAK to abort
- * (will abort on timeout)
- * The acknowledge is NOT sent by cisgetsec; the caller must send a '.'
- * when it is ready to proceed.
- */
- cisgetsec(buf, maxcount)
- char *buf;
- {
- char *p;
- int count;
-
- reread:
- for(;;) {
- if((firstch=readbyte(400)) == SOH)
- break;
- if(firstch==TIMEOUT)
- return ERROR;
- if(firstch==NAK)
- return ERROR;
- }
- ciscursec = oldcrc = readbyte(400);
- for(p=buf, count=0; ;) {
- switch(firstch=readbyte(400)) {
- case TIMEOUT:
- return ERROR;
- case NAK:
- return ERROR;
- case ETX:
- if((firstch=readbyte(400))==TIMEOUT)
- return ERROR;
- if(firstch==DLE) {
- if((firstch=readbyte(400))==TIMEOUT)
- return ERROR;
- firstch &= 037;
- }
- if(firstch == oldcrc)
- return count;
- if (CISasc)
- lprintf("\n");
- lprintf("Error Checksum=0%o Got 0%o \n",
- oldcrc, firstch);
- ++toterrs; sendbyte('/'); goto reread;
- case EOT:
- ciscursec = EOT; break;
- case DLE:
- if((firstch=readbyte(400))==TIMEOUT)
- return ERROR;
- firstch &= 037;
- }
- if(++count > maxcount)
- return ERROR;
- *p++ = firstch;
- if(CISasc)
- putcty(firstch);
- ucksum();
- }
- }
- /*
- * ucksum updates oldcrc with firstch
- * CIS uses rotate left, NOT shift left as per protocol.cis
- */
- ucksum()
- {
- oldcrc += oldcrc;
- if(oldcrc & 0400)
- ++oldcrc;
- if( (oldcrc = (oldcrc & 0377) + firstch) & 0400)
- ++oldcrc;
- oldcrc &= 0377;
- }